package com.stream;

import com.google.common.collect.Lists;
import com.jvm.Math;
import lombok.Builder;
import lombok.Data;

import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @Description 一个stream，在一个管道内，分为三个步骤，
 * 第一步：创建stream，从集合、数组中获取一个流
 * 第二步：是中间操作链，对数据进行处理，如：filter、map
 * 第三步：是终端操作，用来执行中间操作链，返回结果,如：collect
 * @Auther dasouche-data
 * @Date 2022/10/279:53 AM
 * 参考博客：https://juejin.cn/post/6844903895789993991#heading-1
 * 待深入理解：
 * 1.todo 快捷键的类注释
 * 2.todo java.util.function类详解
 * 3.todo java.util.Optional类详解
 */
public class StreamTestTwo {
    public static void main(String[] args) {
        /**
         * 1.创建流
         */
        //1.1集合创建，依赖于collection接口的两个方法 stream()返回一个顺序流,和parallelStream():返回一个并行流
        ArrayList<Integer> integerList = new ArrayList<>();
        integerList.add(1);
        integerList.add(2);
        Stream<Integer> stream = integerList.stream();
        Stream<Integer> integerStream = integerList.parallelStream();

        //1.2数组创建，依赖于Arrays的静态方法stream();
        int[] intArray = {1, 2, 3};
        IntStream stream1 = Arrays.stream(intArray);

        //1.3值创建，依赖于Stream().of(),创建一个流
        Stream<? extends Serializable> stream2 = Stream.of(1, 2, 3, "4", "8", 9.9);
        Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 4, 56, 6);

        //1.4函数创建，依赖于Stream.iterate()和Stream.generate()创建无限流
        Stream.generate(Math::new).limit(5).forEach(System.out::println);//无限顺序无序的流
        Stream.iterate(0, i -> i + 1).limit(5).collect(Collectors.toList());//无限顺序有序的流

        /**
         * 2.流的中间操作
         */
        //2.1distinct():去重,通过流生成的hasCode()和equals()去重元素
        ArrayList<User> arrayList = Lists.newArrayList();
        arrayList.add(User.builder().age(15).name("A").money(Arrays.asList(12, 13, 10)).build());
        arrayList.add(User.builder().age(16).name("b").money(Arrays.asList(12, 13, 151)).build());
        arrayList.add(User.builder().age(17).name("a").money(Arrays.asList(12, 13, 15)).build());
        arrayList.add(User.builder().age(19).name("AA").money(Lists.newArrayList(23, 23, 90)).build());
        arrayList.stream().distinct().forEach(user -> System.out.println(user.toString()));

        //2.2filter()断言行接口；获取大于15岁的数据
        arrayList.stream().filter(user -> user.getAge() > 15).forEach(user -> System.out.println(user.getName()));
        //2.3sort()指定比较规则进行排序
        arrayList.stream().sorted(Comparator.comparing(User::getAge).reversed()).forEach(user -> System.out.println(user.getName()));
        //2.4limit()截断流，使其不超过指定数量
        arrayList.stream().sorted(Comparator.comparing(User::getAge)).limit(1).forEach(user -> System.out.println(user.getAge()));
        //2.5skip()跳过元素,【返回 扔掉前n个元素后--剩下元素组成的流】
        arrayList.stream().sorted(Comparator.comparing(User::getAge)).skip(1).forEach(user -> System.out.println(user.getName()));
        //2.6map()把原始的stream转换成新的stream，具体类：mapToInt、mapToLong、mapToDouble
        //接受function函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素，也就是转换操作；
        arrayList.stream().sorted(Comparator.comparing(User::getAge)).map(user -> "欢迎你" + user.getName()).forEach(System.out::println);
        //2.7flatMap()将流中的每一个值都转换成一个流，然后把所有流连接成一个流;具体类型的方法：flatMapToInt、flatMapToLong、flatMapToDouble、
        arrayList.stream().sorted(Comparator.comparing(User::getAge)).map(user -> user.getMoney()).forEach(System.out::println);
        arrayList.stream().sorted(Comparator.comparing(User::getAge)).flatMap(user -> user.getMoney().stream()).forEach(System.out::println);


        /**
         * 3.终端操作，终端操作执行中间操作链
         */
        //3.1forEach:内部迭代
        arrayList.stream().forEach(user -> System.out.println(user.getName()));
        //3.2collect(Collector collector):收集、将流转换为其他形式，比如转换List、Set、Map;Collectors实用类提供了很多静态方法，可以方便的创建常见搜集器实例
        arrayList.stream().map(User::getName).collect(Collectors.toList());
        arrayList.stream().map(User::getName).collect(Collectors.toSet());
        arrayList.stream().collect(Collectors.toMap(User::getName, Function.identity(), (k1, k2) -> k2));//收集到map,名字作为key,user对象作为value

        //3.3boolean allMatch();检查是否匹配所有元素
        boolean b = arrayList.stream().allMatch(a -> a.getAge() > 10);
        //3.4boolean anyMatch();检查是否至少匹配一个元素
        boolean b1 = arrayList.stream().anyMatch(a -> a.getName().equals("A"));
        //3.5boolean noneMatch();检查是否没有匹配所有元素
        boolean a1 = arrayList.stream().noneMatch(a -> a.getAge() > 90);
        //3.6Optional findFirst();返回当前流中的第一个元素
        Optional<User> first = arrayList.stream().sorted(Comparator.comparing(User::getAge)).findFirst();
        //3.7Optional findAny();返回当前流中的任意元素
        Optional<User> findAny = arrayList.stream().sorted(Comparator.comparing(User::getAge)).findAny();
        //3.8long count();返回流中元素总数
        long count = arrayList.stream().count();
        //3.9 Optional max(Comparator comparator)返回流中最大值
        Optional<Integer> max = arrayList.stream().collect(Collectors.mapping(User::getAge, Collectors.toList())).stream().max(Comparator.comparing(Integer::intValue));
        //3.10 Optional min(Comparator comparator)返回流中最小值
        Optional<Integer> min = arrayList.stream().collect(Collectors.mapping(User::getAge, Collectors.toList())).stream().min(Comparator.comparing(Integer::intValue));
        //3.11reduce(identity,binaryOperator accumulator);可以将流中元素反复结合起来，得到一个值，返回T,这是一个归约操作
        //执行reduction在此留中的元素，使用所提供的身份，积累和组合功能
        List<Integer> collect = arrayList.stream().collect(Collectors.mapping(User::getAge, Collectors.toList()));
        Integer reduce = collect.stream().reduce(0, Integer::sum);
        System.out.println("终端操作测试");
    }
}

/**
 * stream 测试使用
 */
@Data
@Builder
class User {
    int age;
    String name;
    List<Integer> money;
}
